import Joi from 'joi';

/**
 * 用户注册验证规则
 */
export const userRegistrationSchema = Joi.object({
  username: Joi.string()
    .alphanum()
    .min(3)
    .max(30)
    .required()
    .messages({
      'string.alphanum': '用户名只能包含字母和数字',
      'string.min': '用户名至少3个字符',
      'string.max': '用户名最多30个字符',
      'any.required': '用户名是必填项'
    }),
  
  email: Joi.string()
    .email()
    .required()
    .messages({
      'string.email': '请输入有效的邮箱地址',
      'any.required': '邮箱是必填项'
    }),
  
  password: Joi.string()
    .min(6)
    .max(128)
    .required()
    .messages({
      'string.min': '密码至少6个字符',
      'string.max': '密码最多128个字符',
      'any.required': '密码是必填项'
    }),
  
  phone_number: Joi.string()
    .pattern(/^[0-9+\-\s()]+$/)
    .min(8)
    .max(20)
    .optional()
    .messages({
      'string.pattern.base': '请输入有效的电话号码',
      'string.min': '电话号码至少8位',
      'string.max': '电话号码最多20位'
    }),

  verification_code: Joi.string()
    .pattern(/^\d{6}$/)
    .required()
    .messages({
      'string.pattern.base': '验证码必须是6位数字',
      'any.required': '邮箱验证码是必填项'
    })
});

/**
 * 用户登录验证规则
 */
export const userLoginSchema = Joi.object({
  email: Joi.string()
    .email()
    .required()
    .messages({
      'string.email': '请输入有效的邮箱地址',
      'any.required': '邮箱是必填项'
    }),
  
  password: Joi.string()
    .required()
    .messages({
      'any.required': '密码是必填项'
    })
});

/**
 * 宠物信息验证规则
 */
export const petInfoSchema = Joi.object({
  name: Joi.string()
    .max(50)
    .optional()
    .allow('')
    .messages({
      'string.max': '宠物名字最多50个字符'
    }),
  
  species: Joi.string()
    .required()
    .max(50)
    .messages({
      'any.required': '宠物品种是必填项',
      'string.max': '品种名称最多50个字符'
    }),
  
  breed: Joi.string()
    .max(50)
    .optional()
    .allow('')
    .messages({
      'string.max': '具体品种最多50个字符'
    }),
  
  color: Joi.string()
    .required()
    .max(50)
    .messages({
      'any.required': '毛色是必填项',
      'string.max': '毛色描述最多50个字符'
    }),
  
  gender: Joi.string()
    .valid('male', 'female', 'male_neutered', 'female_neutered', 'unknown')
    .required()
    .messages({
      'any.only': '性别必须是male、female、male_neutered、female_neutered或unknown',
      'any.required': '性别是必填项'
    }),
  
  age: Joi.number()
    .integer()
    .min(0)
    .max(30)
    .optional()
    .messages({
      'number.integer': '年龄必须是整数',
      'number.min': '年龄不能小于0',
      'number.max': '年龄不能大于30'
    }),
  
  description: Joi.string()
    .max(1000)
    .optional()
    .allow('')
    .messages({
      'string.max': '描述最多1000个字符'
    })
});

/**
 * 寻宠帖子验证规则
 */
export const postSchema = Joi.object({
  pet_id: Joi.number()
    .integer()
    .positive()
    .required()
    .messages({
      'number.integer': '宠物ID必须是整数',
      'number.positive': '宠物ID必须是正数',
      'any.required': '宠物ID是必填项'
    }),

  last_seen_location: Joi.string()
    .required()
    .max(255)
    .messages({
      'any.required': '最后目击地点是必填项',
      'string.max': '地点描述最多255个字符'
    }),

  last_seen_time: Joi.date()
    .required()
    .max('now')
    .messages({
      'any.required': '最后目击时间是必填项',
      'date.max': '最后目击时间不能是未来时间'
    }),

  video_url: Joi.string()
    .uri()
    .optional()
    .allow('')
    .messages({
      'string.uri': '视频URL格式不正确'
    }),

  contact_info: Joi.string()
    .max(255)
    .optional()
    .allow('')
    .messages({
      'string.max': '联系方式最多255个字符'
    })
});

/**
 * 帖子状态更新验证规则
 */
export const postStatusUpdateSchema = Joi.object({
  post_status: Joi.string()
    .valid('searching', 'found', 'closed')
    .required()
    .messages({
      'any.only': '帖子状态必须是searching、found或closed',
      'any.required': '帖子状态是必填项'
    })
});

/**
 * 管理员审核验证规则
 */
export const adminReviewSchema = Joi.object({
  admin_status: Joi.string()
    .valid('pending', 'approved', 'rejected')
    .required()
    .messages({
      'any.only': '审核状态必须是pending、approved或rejected',
      'any.required': '审核状态是必填项'
    }),

  reason: Joi.string()
    .max(500)
    .optional()
    .allow('')
    .messages({
      'string.max': '审核理由最多500个字符'
    })
});

/**
 * 管理员更新帖子验证规则（包含宠物信息）
 */
export const adminPostUpdateSchema = Joi.object({
  last_seen_location: Joi.string()
    .max(255)
    .optional()
    .messages({
      'string.max': '地点描述最多255个字符'
    }),

  last_seen_time: Joi.date()
    .max('now')
    .optional()
    .messages({
      'date.max': '最后目击时间不能是未来时间'
    }),

  post_status: Joi.string()
    .optional()
    .messages({
      'string.base': '帖子状态必须是字符串'
    }),

  video_url: Joi.string()
    .uri()
    .optional()
    .allow('')
    .messages({
      'string.uri': '视频URL格式不正确'
    }),

  contact_info: Joi.string()
    .max(255)
    .optional()
    .allow('')
    .messages({
      'string.max': '联系方式最多255个字符'
    }),

  pet: Joi.object({
    name: Joi.string()
      .max(100)
      .optional()
      .messages({
        'string.max': '宠物名字最多100个字符'
      }),

    species: Joi.string()
      .max(50)
      .optional()
      .messages({
        'string.max': '物种最多50个字符'
      }),

    breed: Joi.string()
      .max(100)
      .optional()
      .messages({
        'string.max': '品种最多100个字符'
      }),

    color: Joi.string()
      .max(100)
      .optional()
      .messages({
        'string.max': '颜色最多100个字符'
      }),

    gender: Joi.string()
      .max(20)
      .optional()
      .messages({
        'string.max': '性别最多20个字符'
      }),

    description: Joi.string()
      .max(1000)
      .optional()
      .allow('')
      .messages({
        'string.max': '描述最多1000个字符'
      })
  }).optional()
});

/**
 * 目击线索验证规则
 */
export const sightingSchema = Joi.object({
  post_id: Joi.number()
    .integer()
    .positive()
    .required()
    .messages({
      'number.integer': '帖子ID必须是整数',
      'number.positive': '帖子ID必须是正数',
      'any.required': '帖子ID是必填项'
    }),
  
  sighting_location: Joi.string()
    .required()
    .max(255)
    .messages({
      'any.required': '目击地点是必填项',
      'string.max': '地点描述最多255个字符'
    }),
  
  sighting_time: Joi.date()
    .required()
    .max('now')
    .messages({
      'any.required': '目击时间是必填项',
      'date.max': '目击时间不能是未来时间'
    }),
  
  description: Joi.string()
    .max(1000)
    .optional()
    .allow('')
    .messages({
      'string.max': '描述最多1000个字符'
    })
});

/**
 * 分页参数验证规则
 */
export const paginationSchema = Joi.object({
  page: Joi.number()
    .integer()
    .min(1)
    .default(1)
    .messages({
      'number.integer': '页码必须是整数',
      'number.min': '页码必须大于0'
    }),

  limit: Joi.number()
    .integer()
    .min(1)
    .max(100)
    .default(10)
    .messages({
      'number.integer': '每页数量必须是整数',
      'number.min': '每页数量至少为1',
      'number.max': '每页数量最多为100'
    })
});

/**
 * 帖子列表查询参数验证规则（包括分页和筛选）
 */
export const postListQuerySchema = Joi.object({
  // 分页参数
  page: Joi.number()
    .integer()
    .min(1)
    .default(1)
    .messages({
      'number.integer': '页码必须是整数',
      'number.min': '页码必须大于0'
    }),

  limit: Joi.number()
    .integer()
    .min(1)
    .max(100)
    .default(10)
    .messages({
      'number.integer': '每页数量必须是整数',
      'number.min': '每页数量至少为1',
      'number.max': '每页数量最多为100'
    }),

  // 筛选参数
  species: Joi.string()
    .max(50)
    .optional()
    .allow('')
    .messages({
      'string.max': '宠物种类最多50个字符'
    }),

  color: Joi.string()
    .max(50)
    .optional()
    .allow('')
    .messages({
      'string.max': '颜色最多50个字符'
    }),

  gender: Joi.string()
    .valid('male', 'female', 'male_neutered', 'female_neutered', 'unknown')
    .optional()
    .allow('')
    .messages({
      'any.only': '性别必须是male、female、male_neutered、female_neutered或unknown'
    }),

  location: Joi.string()
    .max(255)
    .optional()
    .allow('')
    .messages({
      'string.max': '地点最多255个字符'
    }),

  keyword: Joi.string()
    .max(100)
    .optional()
    .allow('')
    .messages({
      'string.max': '关键词最多100个字符'
    }),

  dateFrom: Joi.date()
    .optional()
    .allow('')
    .messages({
      'date.base': '起始日期格式不正确'
    }),

  dateTo: Joi.date()
    .optional()
    .allow('')
    .messages({
      'date.base': '结束日期格式不正确'
    }),

  post_status: Joi.string()
    .valid('searching', 'found', 'closed')
    .optional()
    .allow('')
    .messages({
      'any.only': '帖子状态必须是searching、found或closed'
    })
});

/**
 * 验证中间件生成器
 * @param {Joi.Schema} schema - Joi验证规则
 * @param {string} source - 验证数据来源 ('body', 'query', 'params')
 */
export function validateRequest(schema, source = 'body') {
  return (req, res, next) => {
    const data = req[source];
    const { error, value } = schema.validate(data, { abortEarly: false });
    
    if (error) {
      const validationErrors = error.details.map(detail => ({
        field: detail.path.join('.'),
        message: detail.message
      }));
      
      return res.status(422).json({
        success: false,
        message: '数据验证失败',
        errors: validationErrors,
        timestamp: new Date().toISOString()
      });
    }
    
    // 将验证后的数据替换原始数据
    req[source] = value;
    next();
  };
}
